package be.gnx.log4jeclipse.perspective.widget;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.spi.LoggingEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import be.gnx.log4jeclipse.log4j.Log4JListenerEvents;
import be.gnx.log4jeclipse.perspective.model.LoggingEvents;
import be.gnx.log4jeclipse.perspective.view.Log4JEntriesEvents;

public class Log4JEntriesWidget extends ScrolledComposite implements Log4JListenerEvents {

  protected static final List<Log4JEntriesEvents> log4JEntriesEventsList = new ArrayList<Log4JEntriesEvents>();

  private LoggingEvents loggingEvents = new LoggingEvents();

  private Display display;

  private Table table;

  public Log4JEntriesWidget(Composite parent, int style) {
    super(parent, style | SWT.H_SCROLL | SWT.V_SCROLL);
    setAlwaysShowScrollBars(false);
    setExpandVertical(true);
    setExpandHorizontal(true);

    display = parent.getDisplay();
    table = new Table(this, SWT.SINGLE | SWT.FULL_SELECTION | SWT.VIRTUAL
        | SWT.BORDER);
    setContent(table);

    table.setLinesVisible(false);
    table.setHeaderVisible(true);

    TableColumn column;
    for (int columnIndex = 0; columnIndex < 6; columnIndex++) {
      column = new TableColumn(table, SWT.LEFT);
      switch (columnIndex) {
      case 0:
        column.setText("Time");
        break;
      case 1:
        column.setText("Machine");
        break;
      case 2:
        column.setText("Priority");
        break;
      case 3:
        column.setText("Category");
        break;
      case 4:
        column.setText("NDC");
        break;
      case 5:
        column.setText("Message");
        break;
      default:
        column.setText("");
        break;
      }
      column.pack();
    }

    TableColumn[] cols = table.getColumns();
    for (int i = 0; i < cols.length; i++) {
      cols[i].setWidth(50);
    }

    table.addListener(SWT.SetData, new Listener() {
      public void handleEvent(Event event) {
        TableItem item = (TableItem) event.item;
        int index = table.indexOf(item);
        LoggingEvent loggingEvent = loggingEvents.get(loggingEvents.size() - index - 1);
        item.setText(0, new Date(loggingEvent.timeStamp).toString());
        item.setText(1, loggingEvent.getThreadName());
        item.setText(2, loggingEvent.getLevel().toString());
        item.setText(3, loggingEvent.getLocationInformation().toString());
        if (loggingEvent.getNDC() != null) {
          item.setText(4, loggingEvent.getNDC());
        } else {
          item.setText(4, "");
        }
        item.setText(5, loggingEvent.getRenderedMessage());
      }
    });

    table.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent selectionEvent) {
        if (selectionEvent.widget instanceof Table) {
          Table table = (Table) selectionEvent.widget;
          for (Log4JEntriesEvents log4JEntriesEvents : log4JEntriesEventsList) {
            log4JEntriesEvents.selectedLoggingEvent(loggingEvents.get(loggingEvents.size() - table
                .getSelectionIndex() - 1));
          }
        }
        super.widgetSelected(selectionEvent);
      }
    });
  }

  public void receivedLoggingEvent(LoggingEvent loggingEvent, String client) {
    loggingEvents.add(loggingEvent);
    display.asyncExec(new Runnable() {
      public void run() {
        if (table.isDisposed()) {
          return;
        }
        table.setItemCount(loggingEvents.size());
        table.clearAll();
        setMinSize(table.getSize());
      }
    });
  }

  public static void addLog4JEntriesEvents(Log4JEntriesEvents log4JEntriesEvents) {
    log4JEntriesEventsList.add(log4JEntriesEvents);
  }

}
